package com.ruoyi.file.service.impl;

import com.ruoyi.file.service.ISysModelFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Service
@Slf4j
public class SysModelFileServiceImpl implements ISysModelFileService {

    /**
     * 下载Excel模板
     * @param response HttpServletResponse对象
     * @param templatePath 模板文件在classpath中的路径
     * @param fileName 下载时的文件名（建议包含.xlsx扩展名）
     * @throws IOException 当文件读取或写入响应流失败时抛出
     */
    @Override
    public void downloadExcelTemplate(HttpServletResponse response, HttpServletRequest request, String templatePath, String fileName) throws IOException {
        // 参数校验
        if (response == null) {
            throw new IllegalArgumentException("HttpServletResponse不能为空");
        }
        if (templatePath == null || templatePath.trim().isEmpty()) {
            throw new IllegalArgumentException("模板路径不能为空");
        }
        if (fileName == null || fileName.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }

        Resource resource = new ClassPathResource(templatePath);

        // 检查资源是否存在
        if (!resource.exists()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "模板文件不存在: " + templatePath);
            return;
        }
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 文件名编码处理，解决中文乱码问题
        this.getFileHeader(fileName, response, request);

        // 使用try-with-resources确保资源正确关闭
        try (InputStream inputStream = resource.getInputStream();
             OutputStream outputStream = response.getOutputStream()) {

            // 获取文件大小（如果可用）
            long contentLength = resource.contentLength();
            if (contentLength > 0) {
                response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
            }

            // 使用更高效的缓冲区大小
            byte[] buffer = new byte[8192]; // 8KB缓冲区
            int bytesRead;
            long totalBytesRead = 0;

            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
                totalBytesRead += bytesRead;
            }

            outputStream.flush();

            // 记录下载日志（可选）
            log.debug("Excel模板下载完成: {}, 文件大小: {} bytes", fileName, totalBytesRead);

        } catch (IOException e) {
            // 记录错误日志
            log.error("下载Excel模板失败: {}, 路径: {}", fileName, templatePath, e);

            // 如果响应还未提交，可以发送错误信息
            if (!response.isCommitted()) {
                response.reset();
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "文件下载失败");
            }
            throw e; // 重新抛出异常，让调用者处理
        }
    }

    /**
     * 文件名编码处理（解决中文乱码问题）
     */
    private void getFileHeader(String fileName,HttpServletResponse response, HttpServletRequest request) throws UnsupportedEncodingException {
        // 处理中文文件名，兼容各种浏览器
        String userAgent = request.getHeader("User-Agent");
        String encodedFileName;

        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            // IE浏览器
            encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
        } else if (userAgent.contains("Firefox")) {
            // Firefox浏览器
            encodedFileName = "=?UTF-8?B?" + Base64.getEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8)) + "?=";
        } else {
            // 其他浏览器
            encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replaceAll("\\+", "%20");
        }

        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
        response.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
        response.setHeader(HttpHeaders.PRAGMA, "no-cache");
        response.setHeader(HttpHeaders.EXPIRES, "0");
    }
}
